package middleware

import (
	"context"
	"encoding/json"
	"fmt"
	"rewords-server-2024/internal/model/input/sysin"
	"sync"
	"time"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"

	"rewords-server-2024/internal/library/cache"
)

// RateLimiter 限流计数器结构
type RateLimiter struct {
	Count      int64      `json:"count"`      // 改为大写
	StartTime  time.Time  `json:"start_time"` // 改为大写
	sync.Mutex `json:"-"` // 添加互斥锁，并在 JSON 序列化时忽略
}

// DefaultRateLimitConfig 默认限流配置
var DefaultRateLimitConfig = sysin.RateLimitConfig{
	Window:      60,           // 60秒
	MaxRequests: 200,          // 每60秒最多200个请求 默认200
	KeyPrefix:   "ratelimit:", // 缓存key前缀
}

// RateLimit 创建限流中间件
func (s *sMiddleware) RateLimit(config ...sysin.RateLimitConfig) func(r *ghttp.Request) {
	cfg := DefaultRateLimitConfig
	if len(config) > 0 {
		cfg = config[0]
	}

	return func(r *ghttp.Request) {
		// 获取客户端IP作为限流键的一部分
		clientIP := r.GetClientIp()
		key := fmt.Sprintf("%s%s", cfg.KeyPrefix, clientIP)

		// 检查是否超过限流阈值
		if !s.checkRateLimit(r.Context(), key, cfg) {
			r.Response.WriteStatus(429, g.Map{
				"code": 429,
				"msg":  "请求过于频繁，请稍后再试",
				"data": nil,
			})
			r.Exit()
			return
		}

		r.Middleware.Next()
	}
}

// checkRateLimit 检查是否超过限流阈值
func (s *sMiddleware) checkRateLimit(ctx context.Context, key string, cfg sysin.RateLimitConfig) bool {
	// 首先尝试获取现有的限流器
	val, err := cache.Instance().Get(ctx, key)
	if err != nil {
		g.Log().Error(ctx, "Rate limit cache error:", err)
		return true // 如果缓存出错，默认放行
	}

	var limiter *RateLimiter
	if val.IsNil() {
		// 如果缓存中不存在，创建新的限流器
		limiter = &RateLimiter{
			Count:     0,
			StartTime: time.Now(),
		}
	} else {
		// 解析现有的限流器
		var stored RateLimiter
		if err := json.Unmarshal([]byte(val.String()), &stored); err != nil {
			g.Log().Error(ctx, "Rate limit unmarshal failed:", err)
			return true
		}
		limiter = &stored

		// 检查是否需要重置计数器
		if time.Since(limiter.StartTime) > time.Duration(cfg.Window)*time.Second {
			limiter.Count = 1 // 重置为1，因为当前请求是第一个
			limiter.StartTime = time.Now()
		} else {
			limiter.Count++
		}
	}

	// 更新缓存
	if err := cache.Instance().Set(ctx, key, limiter, time.Duration(cfg.Window)*time.Second); err != nil {
		g.Log().Error(ctx, "Rate limit cache update error:", err)
	}

	// 检查是否超过限制
	return limiter.Count <= int64(cfg.MaxRequests)
}

// APIRateLimit API限流中间件（针对特定API的限流）
func (s *sMiddleware) APIRateLimit(path string, config ...sysin.RateLimitConfig) func(r *ghttp.Request) {
	cfg := DefaultRateLimitConfig
	if len(config) > 0 {
		cfg = config[0]
	}

	return func(r *ghttp.Request) {
		// 获取客户端IP和API路径作为限流键的一部分
		clientIP := r.GetClientIp()
		key := fmt.Sprintf("%s%s:%s", cfg.KeyPrefix, clientIP, path)

		// 检查是否超过限流阈值
		if !s.checkRateLimit(r.Context(), key, cfg) {
			r.Response.WriteStatus(429, g.Map{
				"code": 429,
				"msg":  "请求过于频繁，请稍后再试",
				"data": nil,
			})
			r.Exit()
			return
		}

		r.Middleware.Next()
	}
}

/**
	func InitRouter() {
    // 全局限流中间件（每个IP每分钟最多100个请求）
    s.Use(service.Middleware().RateLimit())

    // 对特定API设置更严格的限流（例如：登录接口每分钟最多5次）
    s.Group("/api/v1", func(group *ghttp.RouterGroup) {
        group.Middleware(service.Middleware().APIRateLimit("/api/v1/login", RateLimitConfig{
            Window:      60,
            MaxRequests: 5,
            KeyPrefix:   "ratelimit:login:",
        }))

        // ... 其他路由配置 ...
    })
}
**/
